package com.sbtr.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageInputStream;

import com.sbtr.exception.CustException;

public class CutImage {

	private CutImage() {
		throw new IllegalStateException("Utility class");
	}

	/**
	 * 分割矩形图片
	 * 
	 * @param x
	 * @param y
	 * @param width
	 * @param height
	 * @return
	 * @throws IOException
	 */
	public static void cutImg(InputStream input, int x, int y, int width, int height,File sourceFile,String suffixName) throws IOException {
		try (ImageInputStream imageIs = ImageIO.createImageInputStream(input);){
			// 指定切分文件的格式，例如 "jpeg" 或 "tiff"
			Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(suffixName);
			ImageReader reader = it.next();
			// 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader避免缓存包含与以前已经读取的图像关联的数据的那些输入部分
			reader.setInput(imageIs, true);
			// 描述如何对流进行解码的类
			ImageReadParam param = reader.getDefaultReadParam();
			// 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。
			Rectangle rect = new Rectangle(x, y, width, height);
			// 提供一个 BufferedImage，将其用作解码像素数据的目标。
			param.setSourceRegion(rect);
			// 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将 它作为一个完整的 BufferedImage 返回
			BufferedImage bi = reader.read(0, param);
			ImageIO.write(bi, suffixName, new FileOutputStream(sourceFile));
		}
	}

	/**
	 * 	矩形裁剪
	 * @param path 需要裁剪的图路径
	 * @param x   距离左边的偏移量裁剪
	 * @param y   距离上边的偏移量裁剪
	 * @param w        裁剪宽度
	 * @param h        裁剪高度
	 * @param sourceFile  裁剪图保存输出路径
	 * @throws IOException 
	 * @throws Exception
	 */
	public static void cutImg(String path, int x, int y, int w, int h, File sourceFile) throws IOException{
		BufferedImage srcImage = ImageIO.read(new File(path));
		if (null == srcImage || w < 0 || h < 0 || null == sourceFile) {
			throw new CustException("参数输入错误");
		}
		int sw = srcImage.getWidth();
		int sh = srcImage.getHeight();
		if ((x + w) > sw || (y + h) > sh) {
			throw new CustException("参数输入错误");
		}
		BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		int[] rgbArray = srcImage.getRGB(x, y, w, h, null, 0, w);
		outImage.setRGB(0, 0, w, h, rgbArray, 0, w);
		ImageIO.write(outImage, "png", new FileOutputStream(sourceFile));
	}
	
	/**
	 * 多边形裁剪
	 * 
	 * @param srcImage      需要裁剪的图
	 * @param xPoints       组成多边形坐标的X
	 * @param yPoints       组成多边形左边的Y
	 * @param outPath       裁剪图保存输出路径
	 * @param isTransparent 多边形裁剪图底色是否透明
	 * @return
	 * @throws Exception
	 */
	public static boolean cropPolygonImage(String inPath, int[] xPoints, int[] yPoints, String outPath,
			boolean isTransparent) throws Exception {
		BufferedImage srcImage = ImageIO.read(new File(inPath));
		int sw = srcImage.getWidth();
		int sh = srcImage.getHeight();
		int minX = Integer.MAX_VALUE;
		int maxX = 0;
		int minY = Integer.MAX_VALUE;
		int maxY = 0;
		for (int i = 0; i < xPoints.length; i++) {
			if (minX > xPoints[i]) {
				minX = xPoints[i];
			}
			if (maxX < xPoints[i]) {
				maxX = xPoints[i];
			}
			if (xPoints[i] > sw) {
				throw new CustException("多边形参数输入错误");
			}
		}
		for (int i = 0; i < yPoints.length; i++) {
			if (minY > yPoints[i]) {
				minY = yPoints[i];
			}
			if (maxY < yPoints[i]) {
				maxY = yPoints[i];
			}
			if (yPoints[i] > sh) {
				throw new CustException("多边形参数输入错误");
			}
		}
		int ow = maxX - minX;
		int oh = maxY - minY;
		if (isTransparent) {
			BufferedImage maskImage = new BufferedImage(sw, sh, BufferedImage.TYPE_INT_ARGB);
			BufferedImage outImage = new BufferedImage(sw, sh, BufferedImage.TYPE_INT_ARGB);

			Graphics2D dstG2d = maskImage.createGraphics();
			dstG2d.setColor(Color.green);
			dstG2d.fillPolygon(xPoints, yPoints, xPoints.length);
			dstG2d.dispose();

			Graphics2D outG2d = outImage.createGraphics();
			outG2d.setComposite(AlphaComposite.Src);
			outG2d.drawImage(srcImage, 0, 0, null); // 背景图

			outG2d.setComposite(AlphaComposite.DstIn);
			outG2d.drawImage(maskImage, 0, 0, null);
			return cropRectangleImage(outImage, minX, minY, ow, oh, outPath);
		} else {
			return cropRectangleImage(srcImage, minX, minY, ow, oh, outPath);
		}
	}

	/**
	 * 矩形裁剪
	 * 
	 * @param srcImage 需要裁剪的图
	 * @param startX   距离左边的偏移量裁剪
	 * @param startY   距离上边的偏移量裁剪
	 * @param w        裁剪宽度
	 * @param h        裁剪高度
	 * @param outPath  裁剪图保存输出路径
	 * @return
	 * @throws Exception
	 */
	public static boolean cropRectangleImage(BufferedImage srcImage, int startX, int startY, int w, int h,String outPath) throws Exception {
		if (null == srcImage || w < 0 || h < 0 || null == outPath) {
			throw new CustException("参数输入错误");
		}
		int sw = srcImage.getWidth();
		int sh = srcImage.getHeight();
		if ((startX + w) > sw || (startY + h) > sh) {
			throw new CustException("参数输入错误");
		}
		BufferedImage outImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		int[] rgbArray = srcImage.getRGB(startX, startY, w, h, null, 0, w);
		outImage.setRGB(0, 0, w, h, rgbArray, 0, w);
		return ImageIO.write(outImage, "png", new FileImageOutputStream(new File(outPath)));
	}
}